package com.mt.restaurant.service.material.impl;

import com.mt.restaurant.dao.material.MaterialOrderDao;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.web.base.PageDTO;
import com.mt.common.core.web.base.PageResultDTO;
import com.mt.common.core.web.base.BaseEntity;
import com.mt.common.core.web.BaseService;
import com.mt.restaurant.entity.material.OrderMaterialRelation;
import com.mt.restaurant.entity.material.SupplyMaterial;
import com.mt.restaurant.service.material.OrderMaterialRelationService;
import com.mt.restaurant.service.material.SupplyMaterialService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mt.restaurant.entity.material.MaterialOrder;
import com.mt.restaurant.service.material.MaterialOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional
public class MaterialOrderServiceBean extends BaseService implements MaterialOrderService {

    private static Logger logger = LogManager.getLogger();

    @Autowired
    private MaterialOrderDao materialOrderDao;

    @Resource
    private RedisTemplate<String, List<MaterialOrder>> redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    OrderMaterialRelationService orderMaterialRelationService;

    @Autowired
    SupplyMaterialServiceBean supplyMaterialService;

    /**
     * 根据分页参数查询材料订单集合
     *
     * @param pageDTO 分页条件
     */
    @Override
    public PageResultDTO findMaterialOrders(PageDTO pageDTO) {
        if (pageDTO.getCurrentPage() != null) {
            pageDTO.setStartIndex((pageDTO.getCurrentPage() - 1) * pageDTO.getPageSize());
        }
        //TODO:请在此校验参数的合法性
        this.validateFindMaterialOrders(pageDTO);
        List<MaterialOrder> materialOrderDTOS = this.materialOrderDao.findMaterialOrders(pageDTO);

		Long totalCount = this.materialOrderDao.findMaterialOrderTotalCount(pageDTO);

        PageResultDTO pageResultDTO = new PageResultDTO();
		pageResultDTO.setTotalCount(totalCount);
        pageResultDTO.setDatas(materialOrderDTOS);

        return pageResultDTO;
    }

    /**
     * 查询全部材料订单集合
     */
    @Override
    public List<MaterialOrder> findAllMaterialOrders() {
        return this.materialOrderDao.findAllMaterialOrders();
    }

    /**
     * 查询所有材料订单集合(只提取ID 和 Name)
     */
    @Override
    public List<MaterialOrder> findAllMaterialOrdersWithIdName() {
        //TODO:请在此校验参数的合法性
        this.validateFindAllMaterialOrdersWithIdName();
        return this.materialOrderDao.findAllMaterialOrdersWithIdName();
    }

    /**
     * 根据名称查询材料订单集合(只提取ID 和 Name)
     *
     * @param materialOrderName 名称
     */
    @Override
    public List<MaterialOrder> findMaterialOrdersWithIdNameByName(String materialOrderName) {
        //TODO:请在此校验参数的合法性
        this.validateFindMaterialOrdersWithIdNameByName(materialOrderName);
        //TODO:缓存取对应参数
        Set<String> keys = stringRedisTemplate.keys("searchData:MaterialOrder_where_materialOrderName_" + materialOrderName);
        List<MaterialOrder> materialOrders = new ArrayList<>();
        if (keys.isEmpty()) {
            materialOrders = this.materialOrderDao.findMaterialOrdersWithIdNameByName(materialOrderName);
            redisTemplate.opsForValue().set("searchData:MaterialOrder_where_materialOrderName_" + materialOrderName, materialOrders, 30, TimeUnit.DAYS);
        } else {
            materialOrders = redisTemplate.opsForValue().get("searchData:MaterialOrder_where_materialOrderName_" + materialOrderName);
        }
        return materialOrders;
    }

    /**
     * 根据ID查询指定的材料订单(只提取ID 和 Name)
     *
     * @param materialOrderId Id
     */
    @Override
    public MaterialOrder findMaterialOrdersWithIdNameById(Long materialOrderId) {
        //TODO:请在此校验参数的合法性
        this.validateFindMaterialOrdersWithIdNameById(materialOrderId);
        return this.materialOrderDao.findMaterialOrdersWithIdNameById(materialOrderId);
    }

    /**
     * 根据ID查询指定的材料订单
     *
     * @param materialOrderId Id
     */
    @Override
    public MaterialOrder findMaterialOrder(Long materialOrderId) {
        //TODO:请在此校验参数的合法性
        this.validateFindMaterialOrder(materialOrderId);
        return this.materialOrderDao.findMaterialOrder(materialOrderId);
    }

    /**
     * 根据ID查询指定的材料订单(包含外键)
     *
     * @param materialOrderId Id
     */
    @Override
    public MaterialOrder findMaterialOrderWithForeignName(Long materialOrderId) {
        //TODO:请在此校验参数的合法性
        this.validateFindMaterialOrderWithForeignName(materialOrderId);
        return this.materialOrderDao.findMaterialOrderWithForeignName(materialOrderId);
    }

    /**
     * 新增材料订单
     *
     * @param materialOrder 实体对象
     */
    @Override
    public MaterialOrder saveMaterialOrder(MaterialOrder materialOrder) {
        //TODO:请在此校验参数的合法性
        this.validateSaveMaterialOrder(materialOrder);
        //TODO:填充公共参数
        this.setSavePulicColumns(materialOrder);
        materialOrder.setStatus("待提交");
        List<SupplyMaterial> supplyMaterialList = materialOrder.getSupplyMaterialList();
        Map<Long, List<SupplyMaterial>> supplyMaterialMap = new HashMap<>();
        //根据供应商id将提交的供应原材料分组
		supplyMaterialMap = supplyMaterialList.stream().collect(Collectors.groupingBy(supplyMaterial -> supplyMaterial.getSupplierId()));
        //每组供应原材料生成一个订单
		supplyMaterialMap.forEach((key, value) -> {
            Double price = value.stream().mapToDouble(SupplyMaterial::getTotalPrice).sum();
            materialOrder.setPrice(price);
            Long rows = this.materialOrderDao.saveMaterialOrder(materialOrder);
            if (rows != 1) {
                String error = "新增保存材料订单出错，数据库应该返回1,但返回了 " + rows;
                throw new BusinessException(error);
            }
            try{
                materialOrder.setOrderMaterialRelationList(this.orderMaterialRelationService.saveOrderMaterialRelations(materialOrder.getEid(),value));
            }catch (Exception e){
                e.printStackTrace();
            }

        });
        return materialOrder;
    }

    /**
     * 更新材料订单
     *
     * @param materialOrder 实体对象
     */
    @Override
    public MaterialOrder updateMaterialOrder(MaterialOrder materialOrder) {
        //TODO:请在此校验参数的合法性
        this.validateUpdateMaterialOrder(materialOrder);
//        orderMaterialRelationService.deleteOrderMaterialRelationByOrderId(materialOrder.getEid());
        deleteMaterialOrder(materialOrder.getEid());
        materialOrder.setEid(null);
        materialOrder.setCreatorId(null);
        materialOrder.setCreateDatetime(null);
        saveMaterialOrder(materialOrder);
        return materialOrder;

    }

    public void updateMaterialOrdeStatus(Long materialOrderId, Integer auditOperate) {
        Long rows = this.materialOrderDao.updateMaterialOrdeStatus(materialOrderId, auditOperate);
        if (rows != 1) {
            String error = "更新材料订单出错，数据可能已经被删除";
            throw new BusinessException(error);
        }
        if(auditOperate==3){
            List<OrderMaterialRelation> orderMaterialRelationList = orderMaterialRelationService.findOrderMaterialsByOrderId(materialOrderId);
            orderMaterialRelationList.forEach(item->{
                supplyMaterialService.updateSupplyMaterialStockById(item.getSupplyMaterialId(),item.getAmount());
            });
        }
    }

    @Override
    public void updateMaterialOrdersStatus(List<MaterialOrder> materialOrderList, Integer operate) {
        Long rows = this.materialOrderDao.updateMaterialOrdersStatus(materialOrderList,operate);
        if(rows != materialOrderList.size()){
            String error = "更新材料订单出错，数据可能已经被删除";
            throw new BusinessException(error);
        }
    }

    /**
     * 根据ID删除材料订单
     *
     * @param materialOrderId ID
     */
    @Override
    public void deleteMaterialOrder(Long materialOrderId) {
        //TODO:请在此校验参数的合法性
        this.validateDeleteMaterialOrder(materialOrderId);
        orderMaterialRelationService.deleteOrderMaterialRelationByOrderId(materialOrderId);
        Map<Class<? extends BaseEntity>, EntityUsage> entityUsageMap = this.checkForeignEntity(MaterialOrder.class, materialOrderId);
        if (entityUsageMap != null && entityUsageMap.size() > 0) {
            StringBuilder errors = new StringBuilder();
            errors.append("计划删除的数据正在被以下数引用\n");
            for (EntityUsage entityUsage : entityUsageMap.values()) {
                errors.append("\t").append(entityUsage.getEntityLabel()).append("\n");
                for (Map.Entry<Long, String> entry : entityUsage.getUsageIdNames().entrySet()) {
                    errors.append("\t\t").append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
                }
            }
            errors.append("，不能删除，请检查处理后再删除");
            throw new BusinessException(errors.toString());
        }

        Long rows = this.materialOrderDao.deleteMaterialOrder(materialOrderId);
        if (rows != 1) {
            String error = "删除材料订单出错，数据可能已经被删除";
            throw new BusinessException(error);
        }
    }



    //TODO:---------------验证-------------------

    private void validateFindMaterialOrders(PageDTO pageDTO) {
        //TODO:请使用下面方法添加数据过滤条件
        //		pageDTO.addFilter("creatorId",this.getLoginUserId());
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateFindMaterialOrdersWithIdNameByName(String materialOrderName) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }


    private void validateFindAllMaterialOrdersWithIdName() {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateFindMaterialOrdersWithIdNameById(Long materialOrderId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateFindMaterialOrder(Long materialOrderId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateFindMaterialOrderWithForeignName(Long materialOrderId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateSaveMaterialOrder(MaterialOrder materialOrder) {
        //不为空判断
        if (materialOrder.getEid() != null || materialOrder.getCreatorId() != null || materialOrder.getCreateDatetime() != null) {
            throw new BusinessException("非法请求");
        }
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateUpdateMaterialOrder(MaterialOrder materialOrder) {
//        if(materialOrder.getStatus()!="待审核"&&materialOrder.getStatus()!="打回"){
//            throw new BusinessException("不允许修改该订单");
//        }
        //不为空判断
        if (materialOrder.getEid() == null) {
            throw new BusinessException("唯一标识不能为空");
        }
        //是否存在判断
        if (this.materialOrderDao.findMaterialOrderTotalCount(PageDTO.create(MaterialOrder.FIELD_ID, materialOrder.getEid())) == 0) {
            throw new BusinessException("修改的材料订单 " + materialOrder.getName() + " 不存在，修改失败，请重试或联系管理员");
        }
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    private void validateDeleteMaterialOrder(Long materialOrderId) {
        //TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateMaterialOrder()写法
    }

    @Override
    public boolean canDownloadAttachment(String formName, Long id) {
        return true;
    }
}
